home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
qtawk
/
fmtdoc.exp
< prev
next >
Wrap
Text File
|
1990-04-29
|
28KB
|
981 lines
# QTAwk program to format ASCII text files
# (C) Copyright 1990 Terry D. Boldt, All Rights Reserved
#
# input: ASCII text file
# output: text formatted into lines of <= 'width' characters
#
# advantages:
# 1) can change easily to suit needs - can add/delete control words as needed
# 2) simple and will easily handle the majority of needs for letters,
# documents, etc.
#
# design philosophy:
# 1) bare minimum of control words in text
# 2) capture more complex formatting tasks in functions, e.g.,
# a) page top margin and running header captured in variables set in BEGIN
# and print_top function
# b) page bottom margin and running footer captured in variables set in
# BEGIN and end_page function
# 3) blank lines cause 'break' in text and line skip
#
# control words:
# .* ==> comment line - ignore
# .br text ==> break and accumulate text for output
# .ce text ==> center 'text' in width
# .ds ==> double space
# .hn ==> 0 <= n <= 9 header command
# .il n ==> indent line n spaces from left indentation
# .im filename ==> imbed file named, only one level of imbedding allowed
# .in [[+/-]n] ==> indentation
# .ll n ==> line length to n
# .hr [on/off][header line ==> turn header printing on/off, set header line
# .fr [on/off][footer line ==> turn footer printing on/off, set footer line
# .pa [n] ==> page eject n times, n == 1 default
# .pn [roman/arabic/alpha/normal/n] ==> set page number & style
# .sp [n] ==> n blank lines, n == 1 default
# .ss ==> single space
# .sx /left/center/right/ ==> split text left - center - right
#
# .pl set page length --> number of lines (includes top/bottom margins & headers
# .tm [n] ==> set top margin to n lines
# .bm [n] ==> set bottom margin to n lines
#
# .tb n text ==> tab n spaces after left margin and print text,
# n == 0 causes break
# .tc [n] ==> reserve n pages for table of contents, n == 1 by default
# .pt line ==> insert "line" in table of contents. Note .tc control must be
# used or Table of Contents not generated
#
# Table formator definition:
# .td (table definition) define separator for input column text
# define start columns for each column of table
# .td " 1 7 14
# " ==> separator for each column in input text
# first column starts at column 1
# second column starts at column 7
# third column starts at column 14
# column numbering starts at left margin
#
# .td c cols ==> define table separator character and columns
# .tl start ==> start table formatting
# .tl stop ==> stop table formatting
#
# :ol. ==> start ordered list
# :sl. ==> start simple list
# :ul. ==> start un-ordered list
# :li. ==> list item
# :eol. ==> stop list (ordered)
# :esl. ==> stop list (simple)
# :eul. ==> stop list (unordered)
#
# .se name = value ==> set substution variable to remainder of input record
# formatted "built-in" variables may be defined in 'BEGIN' and
# 'INITIAL' sections also.
#
# .se on/off turn variable replacement on/off - default is on at start
#
BEGIN {
lstb[0] = '^';
lstb[1] = '.';
lstb[2] = ')';
lstb[3] = ':';
lstb[4] = '|';
lstb[5] = '>';
lstb[6] = '}';
lstb[7] = ']';
lstb[8] = '*';
lstb[9] = '_';
olstn = 10;
d_page_length = page_length = 66; # page length at 6 lines per inch
d_top_margin = top_margin = 6; # number of lines reserved for top margin
d_bot_margin = bot_margin = 6; # number of lines reserved for bottom margin
d_width = 65; # default width of text == line length
width = 65; # width of text == line length
d_left_m = 8; # default number of blanks on left margin
left_m = 8; # number of blanks on left margin
header = FALSE;
footer = TRUE;
hdr_line = dhdr_line = "||- # -||"; # header line
ftr_line = dftr_line = "||- # -||"; # footer line
toc_hdr_line = "|||Table of Contents|"; # header line
toc_ftr_line = dftr_line; # Footer line
hdr_lines = 1; # number of lines in page header
hdr_skip = 2; # number of blank lines after header line(s)
ftr_lines = 1; # number of lines in page footer
ftr_skip = 2; # number of blank lines before footer line(s)
# default number of text body lines/page
# == 54 lines default
num_lines = page_length - top_margin - bot_margin - (header * (hdr_lines - hdr_skip)) - (footer * (ftr_lines - ftr_skip));
ttl_page_cnt = 1; # indexpendent count of pages
page_num = 1; # page number
page_num_prefix = ""; # page number prefix string
reset_headr_0 = FALSE; # flag to set page number to 1 on ".ho" command
left_margin = copies(" ",left_m); # left margin blanks
double_space = FALSE; # double spacing output
roman_num = FALSE; # page numbering in arabic or roman
alpha_num = FALSE; # page numbering in alphabetic
adjust = 5; # justify lines if size within adjust of width
wait_on_page = FALSE; # TRUE if wait at end of page
para_indent = 1; # number of blanks less one - first
# line of para. indented
para_start = FALSE; # flag whether line starts new para.
format = TRUE; # format flag
right_justify = 10; # format value to right justify text
left_justify = 20; # format value to left justify text
table_format = format;# variable to hold format value while doing table
var_replace = TRUE; # default to replace variables
req_be = /\x0ff/; # required blank - tranlated to blank just prior to output
# above regular expression version
req_bs = '\x0ff'; # required blank - tranlated to blank just prior to output
# above string version
# need both regular expression version and string version
# to get speed of r.e. search and replacement
# and string to place hexadecimal character in output
split(sdate(2),date,/\//);
sysyear = date[3];
sysmonth = date[2];
sysdayofm = date[1];
sysdayofw = ((jdn(sysyear,sysmonth,sysdayofm) + 1) % 7) + 1;
sysdayofy = sdate(16);
date1 = sdate(1); # set today's date variable
date2 = sdate(2); # set today's date variable
date3 = sdate(3); # set today's date variable
date4 = sdate(4); # set today's date variable
date5 = sdate(5); # set today's date variable
date6 = sdate(6); # set today's date variable
date7 = sdate(7); # set today's date variable
date8 = sdate(8); # set today's date variable
date9 = sdate(9); # set today's date variable
date = date9;
time = stime(4); # set document format time
fnum = /^{_i}$/; # regular expression for recognizing numeric fields
stx_chr = ' '; # character used by split_text function for mask line
stderr = "stderr";
stdin = "stdin";
cstart = "start";
cstop = "stop";
no = "no";
yes = "yes";
on = "on";
off = "off";
right = "right";
left = "left";
hnum = major_sctn = minor_sctn = 0;
imbedded_file = FALSE;
tc_cnt = 0;
#
# following variables define printer control sequences
# currently set for IBM Proprinter
#
# turn emphasized printing on/on
emph_on = "\x01b\x045";
emph_off = "\x01b\x046";
# Continuous Underscore on/off
cus_on = "\x01b-\x001";
cus_off = "\x01b-\x080";
# Condensed Print on/off
condsd_on = '\x00f';
condsd_off = '\x012';
# start/stop Letter Quality Print - proprinter
lttrq_on = "\x01bI\x002";
lttrq_off = "\x01bI\x080";
# start/stop Letter Quality Print - color printer
lttrq_on_cp = "\x01bI\x003";
lttrq_off_cp = "\x01bI\x002";
# sub/super-script
sub_on = "\x01bS\x001";
sup_on = "\x01bS\x080";
# Cancel sub/super-script Printing
sub_sup_off = "\x01bT";
# set ribbon color - color printer
band_1 = "\x01by"; # yellow
band_2 = "\x01bm"; # red
band_3 = "\x01bc"; # blue
band_4 = "\x01bb"; # black
#
# printer initialization strings would be printed here, e.g.,
# to turn on built-in letter quality print, the following
# print statement is used:
printf(lttrq_on);
#
# intialize printing - print header blank lines
# use in BEGIN actions for single document from many
# use in INITIAL actions for many single documents
#
#} # remove comment at line beginning for many documents
# INITIAL { # remove comment at line beginning for many documents
top = TRUE;
}
GROUP /^{_w}*$/ { # blank input line - allow for possible blanks and tabs
printline(no);
if ( !top ) output_line("",TRUE); # do not output blanks if at top of page
para_start = TRUE;
size += para_indent;
next;
}
GROUP /^\.\*/ { # comment line - ignore
next;
}
# replace defined variables in format {named_variable} in input record
{
if ( var_replace ) $0 = replace($0); # replace variables
}
GROUP /^\.sr/ { # set from addressee
sender[sr_line++] = strim(substr($0,4));
$1 = ".tb 35";
cycle;
}
GROUP /^\.ad/ { # format addressee
addressee[ad_line++] = strim(substr($0,4));
$1 = ".br";
cycle;
}
GROUP /^\.fo/ { # format on/off command
switch ( $2 ) {
case on:
format = TRUE;
break;
case off:
format = FALSE;
break;
case right:
format = right_justify;
break;
case left:
format = left_justify;
break;
default:
fprintf(stderr,"Incorrect format '.fo' command.\nFile: %s\nLine: %u\n",FILENAME,FNR);
exit 2;
break;
}
printline(no);
next;
}
GROUP /^\.br/ { # break command
printline(no);
if ( NF > 1 ) {
$0 = strim(substr($0,4));
add_line;
}
next;
}
GROUP /^\.ce/ { # command to center line
local tcnt, tline;
printline(no);
tcnt = split(strim(substr($0,4)),tline);
tline = form_line(tline,tcnt,width,left_justify);
output_line(center(tline,width),TRUE);
next;
}
GROUP /^\.il/ { # indent next line n spaces
printline(no);
if ( $2 ~~ fnum ) # check if 2nd field an integer
addword(copies(" ",$2));
next;
}
GROUP /^\.im/ {
if ( !imbedded_file ) {
ARGI --;
FILENAME = $2;
imbedded_file = TRUE;
fprintf(stderr,"Imbedded File: %s [Page: %s (%u)\n",FILENAME,set_pnum(page_num),ttl_page_cnt);
} else {
fprintf(stderr,"Only One Level Of File Imbedding Allowed.\nFile: %s\nLine: %u\n",FILENAME,FNR);
exit 200;
}
next;
}
GROUP /^\.in/ { # set indentation
if ( $2 ~~ fnum ) {
if ( $2 ~~ /^[+-]/ ) {
left_m += $2;
if ( left_m < 0 ) left_m = d_left_m;
} else left_m = $2;
} else left_m = d_left_m;
left_margin = copies(" ",left_m);
next;
}
GROUP /^\.ll/ { # set line length
if ( $2 ~~ fnum ) width = $2; # check if 2nd field an integer
else width = d_width; # set line length if TRUE
next;
}
GROUP /^\.h[0-9]/ {
local hl, i, hnm;
printline(no);
hl = int(substr($$0,3,1));
if ( hl < head_level ) {
for ( i = hl + 1 ; i < 10 ; i++ ) hla[i] = 0;
} else if ( hl > head_level + 1 ) {
fprintf(stderr,"Error - Incorrect Head Level Specified.\nInput File: %s\nRecord Number: %u",FILENAME,FNR);
exit 10;
}
if ( !(head_level = hl) ) {
if ( !top ) page_eject;
if ( !(page_num & 1) ) page_eject;
if ( reset_headr_0 ) page_num = 1;
}
++hla[hl];
hnum = hla[0] "";
if ( hl ) {
minor_sctn = hla[hl];
for ( i = 1 ; i <= hl ; i++ ) hnum ∩= "." hla[i];
hnm = hnum;
} else {
major_sctn++;
minor_sctn = 0;
hnum ∩= ".0";
hnm = cus_on ∩ hnum;
toc_lines[tc_cnt]["skip"] = TRUE;
}
$1 = hnum;
toc_lines[tc_cnt]["line"] = $0;
toc_lines[tc_cnt]["pgn"] = set_pnum(page_num);
tc_cnt++;
$1 = emph_on ∩ hnm ∩ " ";
$0 ∩= emph_off;
if ( !hl ) $0 ∩= cus_off;
add_line;
printline(no);
next;
}
GROUP /^\.hr/ {
if ( NF > 1 ) {
switch ( $2 ) {
case on:
header = TRUE;
break;
case off:
header = FALSE;
break;
default:
hdr_line = strim(substr($0,4));
break;
}
} else hdr_line = dhdr_line;
next;
}
GROUP /^\.fr/ {
if ( NF > 1 ) {
switch ( $2 ) {
case on:
footer = TRUE;
break;
case off:
footer = FALSE;
break;
default:
ftr_line = strim(substr($0,4));
break;
}
} else ftrline = dftr_line;
next;
}
GROUP /^\.pl/ { # set page length in lines # check if 2nd field an integer
# set page length if TRUE
if ( $2 ~~ fnum ) page_length = $2;
else page_length = d_page_length;
num_lines = page_length - top_margin - bot_margin - (header * (hdr_lines - hdr_skip)) - (footer * (ftr_lines - ftr_skip));
next;
}
GROUP /^\.tm/ { # set top margin
if ( $2 ~~ fnum ) top_margin = $2;
else top_margin = d_top_margin;
num_lines = page_length - top_margin - bot_margin - (header * (hdr_lines - hdr_skip)) - (footer * (ftr_lines - ftr_skip));
next;
}
GROUP /^\.bm/ { # set bottom margin
if ( $2 ~~ fnum ) bot_margin = $2;
else bot_margin = d_bot_margin;
num_lines = page_length - top_margin - bot_margin - (header * (hdr_lines - hdr_skip)) - (footer * (ftr_lines - ftr_skip));
next;
}
GROUP /^\.pa/ { # page eject
local num_ejects;
if ( !top ) page_eject;
if ( $2 ~~ fnum ) { # check if second field an integer
num_ejects = $2 - 1;
while ( num_ejects-- ) page_eject; # use 'page_eject' function in
} # order to get ejected pages
next; # numbered
}
GROUP /^\.pn/ { # page numbering
if ( NF > 1 ) {
i = 2;
do {
switch ( strlwr($i) ) {
case fnum:
if ( $i ~~ /^[-+]/ ) page += $i; else page_num = $i;
break;
case "alpha":
alpha_num = TRUE;
roman_num = FALSE;
break;
case "roman":
roman_num = TRUE;
alpha_num = FALSE;
break;
case "arabic":
case "normal":
roman_num = alpha_num = FALSE;
break;
}
} while ( ++i <= NF );
} else page_num = 1;
next;
}
GROUP /^\.ds/ { # double space
double_space = TRUE;
next;
}
GROUP /^\.se/ { # set variable
switch ( $2 ) {
case on:
var_replace = TRUE; # turn on variable replacement
break;
case off:
var_replace = FALSE; # turn off variable replacement
break;
default:
$1 = "";
if ( $0 !~ /;$/ ) $0 ∩= ';';
execute($0);
break;
}
next;
}
GROUP /^\.ss/ { # single space
double_space = FALSE;
next;
}
GROUP /^\.sp/ { # line spaces
local num_spaces = 1;
printline(no);
if ( $2 ~~ fnum ) num_spaces = $2; # check if 2nd field an integer
while ( num_spaces-- ) output_line("",TRUE); # print blank lines for line skips
next;
}
GROUP /^\.sx/ { # command to split text
printline(no);
output_line(split_text(strim(substr($0,4)),width),TRUE);
cnt = 0;
next;
}
GROUP /^\.tb/ { # command to tab over nn spaces
local ol;
printline(no);
# check if second field an integer
if ( $2 ~~ fnum ) {
ol = copies(" ",$2);
$2 = "";
}
$1 = "";
ol ∩= strim($0);
output_line(ol,TRUE);
next;
}
# start ordered list
GROUP /^:ol\./ {
printline(no);
list_list[++list_level] = 1;
left_margin = copies(" ",length(left_margin) + 4);
width -= 4;
olist++;
next;
}
# start simple list
GROUP /^:sl\./ {
printline(no);
list_list[++list_level] = -1;
left_margin = copies(" ",length(left_margin) + 4);
width -= 4;
next;
}
# start un-ordered list
GROUP /^:ul\./ {
printline(no);
list_list[++list_level] = 0;
left_margin = copies(" ",length(left_margin) + 4);
width -= 4;
ulist++;
next;
}
# list item
GROUP /^:li\./ {
if ( list_level ) {
printline(no);
$0 = strim(substr($0,5));
list_item;
}
next;
}
# end [un-]ordered list
GROUP /^:e[osu]l\./ {
if ( list_level ) {
printline(no);
--list_level;
left_margin = copies(" ",length(left_margin) - 4);
width += 4;
list_left_mh = FALSE;
if ( substr($0,3,1) == 'o' && olist ) olist--;
else if ( substr($0,3,1) == 'u' && ulist ) ulist--;
}
next;
}
# table of contents command
# .tc n - n == number of pages to reserve, default == 1
GROUP /^\.tc/ {
local toc_pages = 1;
if ( !top ) page_eject;
toc_pnum = page_num;
if ( NF > 1 && $2 ~~ fnum ) toc_pages = $2;
page_num += toc_pages;
next;
}
# put a line into table of contents
GROUP /^\.pt/ {
local r_num = set_pnum(page_num);
toc_lines[tc_cnt]["pgn"] = r_num;
$0 = strim(substr($0,4));
toc_lines[tc_cnt]["line"] = $0;
toc_lines[tc_cnt]["skip"] = FALSE;
tc_cnt++;
next;
}
# command to define table
# $2 == table separator
# $3 ... $NF == table columns starts
GROUP /^\.td/ {
local i, j;
t_sep = $2;
if ( NF > 2 ) {
deletea t_col;
for ( i = 3 , j = 1 ; i <= NF ; i++ , j++ ) {
t_col[j] = $i;
}
}
next;
}
# start/stop table formatting
GROUP /^\.tl/ {
local f2 = strlwr($2);
if ( f2 == cstart ) {
printline(no);
table_f = TRUE;
table_format = format;
format = FALSE;
} else if ( f2 == cstop ) {
table_f = FALSE;
format = table_format;
} else {
fprintf(stderr,"'tl' Command Only Recognizes 'start' or 'stop'.\n");
exit 3;
}
next;
}
{
if ( format ) add_line;
else if ( table_f ) format_table($0);
else output_line($0,TRUE);
}
# end of file - clean up between files
FINAL {
local dummy;
imbedded_file = FALSE;
if ( ad_line ) {
# printline(no);
if ( !top ) page_eject;
fprintf(stderr,"Place Envelope in Printer\nPress Enter");
fgetline(stdin,dummy);
for ( sr_line in sender ) printf(" %s\n",sender[sr_line]);
printf(copies('\n',8));
for ( ad_line in addressee ) printf("\t\t\t\t\t%s\n",addressee[ad_line]);
printf("\f");
sr_line = FALSE;
ad_line = FALSE;
}
}
# end of file - clean up and eject last page
END { # use for single document
if ( toc_pnum ) print_toc;
if ( !top ) page_eject;
}
# function to add current line to parsed text
function add_line() {
for ( i = 1 ; i <= NF ; i++ ) if ( length($i) ) addword($i);
}
# output accumulated words
function output_line(oline,leftm) {
if ( top ) print_top;
if ( leftm ) printf(left_margin);
if ( list_left_mh ) {
left_margin = list_left_mh;
list_left_mh = FALSE;
}
gsub(req_be," ",oline);
print oline;
line_cnt += 1 + double_space; # increment line counter
if ( line_cnt >= num_lines ) # check for end of page
end_page; # function to print page numbers - note absence
# of '()' to invoke
else if ( double_space ) print "";
}
# accumlate words for line
function addword(w) {
local lw = length(w); # length of added word
if ( cnt + size + lw > width ) printline(yes); # check new line length
line[++cnt] = w; # add word to line array
size += lw;
}
# print accumulated words in justified line
function printline(f) {
local i, nb, nsp, holes;
local tline;
local adj = adjust + cnt;
local fmt = format;
if ( cnt ) {
if ( para_start && para_indent ) line[1] = copies(" ",para_indent) line[1];
if ( strlwr(f) == no && size < (width - adj) ) fmt = fmt < right_justify ? left_justify : fmt;
tline = form_line(line,cnt,width,fmt);
output_line(tline,TRUE);
if ( set_width ) {
width = set_width;
set_width = FALSE;
}
size = cnt = 0;
deletea line;
}
if ( para_start ) para_start = FALSE;
}
# eject current page - print blank lines to bottom,
# print page number and form feed
function page_eject() {
printline(no);
while ( ++line_cnt <= num_lines ) print "";
end_page;
}
# end of page clean up - print page number & eject
function end_page() {
local pnl = replace(ftr_line); # replace defined variables in footer
local r_num = set_pnum(page_num);
local left_margin = copies(" ",d_left_m);
local ftrs = ftr_skip;
if ( footer ) {
while ( ftrs-- ) print "";
sub(/#/,r_num,pnl); # substitute for page number
# print left margin and footer text split across default page width
print left_margin split_text(pnl,d_width);
# use following line if want text centered instead of split
# print left_margin center(pnl,width);
}
printf("\f");
line_cnt = 0;
top = TRUE;
if ( wait_on_page ) { # if waiting at end of page - display message, wait
fprintf(stderr,"Insert New Page, Press Carriage Return\n");
fgetline(stdin,pnl);
}
fprintf(stderr,"Finished Page: %s (%u)\n",set_pnum(page_num),ttl_page_cnt);
page_num++;
ttl_page_cnt++;
}
# print top margin and header if any
function print_top() {
local hdr_lne = replace(hdr_line); # replace defined variables in header
local r_num = set_pnum(page_num);
local left_margin = copies(" ",d_left_m);
local hdrs = hdr_skip;
top = FALSE;
# print top margin
while ( ++line_cnt <= top_margin ) print "";
if ( header ) {
sub(/#/, r_num , hdr_lne ); # substitute for page number
# print left margin and header text split across default page width
print left_margin split_text(hdr_lne,d_width);
# use following line if want text centered instead of split
# print left_margin center(hdr_lne,width);
while ( hdrs-- ) { print ""; line_cnt++; }
}
}
# function to convert decimal number to roman numeral
# used if roman numeral page numbering desired - see roman_num variable
function roman_numeral(num) {
# pwr_ten ==> maximum integer representable as roman numeral
local i, pwr_ten = 10000;
local frst_sym = '?', secd_sym = 'm', thrd_sym = '?';
local num_str = "";
local three_sym;
num = int(num);
if ( num <= pwr_ten )
do {
pwr_ten /= 10;
i = num / pwr_ten;
num -= i * pwr_ten;
three_sym = "";
switch ( i ) {
case 3:
num_str ∩= secd_sym;
case 2:
num_str ∩= secd_sym;
case 1:
num_str ∩= secd_sym;
break;
case 4:
num_str ∩= secd_sym;
num_str ∩= thrd_sym;
break;
case 5:
num_str ∩= thrd_sym;
break;
case 8:
three_sym ∩= secd_sym;
case 7:
three_sym ∩= secd_sym;
case 6:
three_sym ∩= secd_sym;
num_str ∩= thrd_sym three_sym;
break;
case 9:
num_str ∩= secd_sym;
num_str ∩= frst_sym;
break;
case 0:
break;
}
switch ( frst_sym = secd_sym ) {
case 'm':
secd_sym = 'c';
thrd_sym = 'd';
break;
case 'c':
secd_sym = 'x';
thrd_sym = 'l';
break;
case 'x':
secd_sym = 'i';
thrd_sym = 'v';
break;
}
} while ( pwr_ten && num );
return num_str;
}
# convert decimal number to alphabetic number - useful if alphabetic page
# numbering wanted
function d_to_alpha(num) {
local num_str = "";
local k;
local alphabet = "abcdefghijklmnopqrstuvwxyz";
num = int(num);
if ( num > 0 && num <= 308915776 ) { # test for maximum number convertable
while ( num > 26 ) {
k = num % 26;
num /= 26;
if ( !k ) {
k = 26;
num--;
}
num_str = substr(alphabet,k,1) num_str;
}
num_str = substr(alphabet,num,1) num_str;
}
return num_str;
}
# function to split text '.sx' control word
function split_text(text,line_width) {
local cnt;
local sx_line, s_line;
local delim = substr(text,1,1);
# split line on delimitor
cnt = split(text,s_line,delim);
# check for three fields
if ( cnt == 3 ) {
# center center portion in 'line_width'
sx_line = center(s_line[2],line_width,stx_chr);
# overlay left portion
sx_line = overlay(sx_line,s_line[1],1);
# overlay right portion
sx_line = overlay(sx_line,s_line[3],line_width - length(s_line[3]) + 1);
} else {
fprintf(stderr,"'.sx' Command Needs 3 Fields.\nLine: %d\nFile: %s\n",FNR,FILENAME);
exit 1;
}
return sx_line;
}
# function to format input lines into table columns
function format_table(iline) {
local oline, ocnt;
local cline, ccnt;
local pline = copies(" ",width);
local i, j;
ocnt = split(iline,oline,t_sep); # split input line into columns
for ( i in t_col ) {
if ( i > ocnt ) break;
ccnt = split(oline[i],cline,/[\s\t]+/); # split column into words
pline = overlay(pline,form_line(cline,ccnt,width,left_justify),t_col[i]);
}
output_line(pline,TRUE);
}
# function to output list item
function list_item() {
local lmrgn = length(left_margin);
local lsth;
local bchr, bhdr, bnum;
local blnk_sep = copies(req_bs,2);
list_left_mh = left_margin;
left_margin = copies(" ",lmrgn - 4);
if ( list_list[list_level] > 0 ) { # ordered list
lsth = lstb[olist % olstn] blnk_sep;
# use numeric for odd levels, alpha for even levels
if ( olist & 1 ) $1 = list_list[list_level]++ lsth $1;
else $1 = d_to_alpha(list_list[list_level]++) lsth $1;
} else if ( !list_list[list_level] ) { # un-ordered list
if ( ulist & 1 ) bchr = '■'; else bchr = '-';
for ( bnum = int((ulist + 1) / 2) ; bnum ; bnum-- ) bhdr = bchr bhdr;
$1 = bhdr blnk_sep $1;
}
set_width = width;
width += 4;
add_line;
}
# function to convert year/month/day into julian day number
function jdn(year,month,day) {
local yr;
local pfac = 0.6;
local ljdn;
yr = year + (month - 3.0) / 12.0;
ljdn = int(367.0 * yr + pfac) - (2 * int(yr)) + int(yr/4.0)
+ int(day) + 1721117;
if ( !greg_jul ) ljdn += -int(yr/100.0) + int(yr/400.0) + 2;
return ljdn;
}
# form array of words into output line
# line ==> array of words
# cnt ==> number of elements in line
# width ==> character width of line to form
# format == 1 justify on width
# format == right_justify || left justify
function form_line(line,cnt,width,format) {
local i, oline;
if ( format > TRUE ) {
for ( i = 2 , oline = line[1] ; i <= cnt ; i++ ) oline ∩= " " line[i];
if ( format == right_justify )
oline = copies(" ",width - length(oline)) ∩ oline;
} else oline = justify(line,cnt,width);
return oline;
}
function print_toc() {
local tline;
local tcnt;
local stx_chr_h = stx_chr;
local hld_hdr = hdr_line;
local hld_ftr = ftr_line;
local prefix_hld = page_num_prefix;
if ( !top ) page_eject;
hdr_line = toc_hdr_line;
ftr_line = toc_ftr_line;
page_num_prefix = "";
alpha_num = FALSE;
roman_num = TRUE;
page_num = toc_pnum;
output_line("Table of Contents",TRUE);
output_line("",TRUE);
for ( tcnt = 0 ; tcnt < tc_cnt ; tcnt++ ) {
if ( toc_lines[tcnt]["skip"] ) output_line("",TRUE);
tline = '\x0ff' ∩ toc_lines[tcnt]["line"] ∩ " " ∩ "\x0ff\x0ff" ∩ " " ∩ toc_lines[tcnt]["pgn"] ∩ '\x0ff';
stx_chr = '.';
tline = split_text(tline,d_width);
stx_chr = stx_chr_h;
output_line(tline,TRUE);
}
if ( !top ) page_eject;
hdr_line = hld_hdr;
ftr_line = hld_ftr;
page_num_prefix = prefix_hld;
}
# return page number aaccording to style set
function set_pnum(pnum) {
local r_num = roman_num ? roman_numeral(pnum) : alpha_num ? d_to_alpha(pnum) : pnum;
return replace(page_num_prefix) ∩ r_num;
}